package com.simple.crawler.core;

import com.simple.crawler.annotation.TaskFeature;
import com.simple.crawler.connect.Request;
import com.simple.crawler.connect.Response;
import com.simple.crawler.constant.Const;
import com.simple.crawler.connect.Connection;
import com.simple.crawler.constant.ExceptionCode;
import com.simple.crawler.exception.CrawlerRuntimeException;
import com.simple.crawler.utils.CrawlerLogger;
import com.simple.crawler.utils.IOUtils;
import com.simple.crawler.utils.ReflectUtils;
import com.simple.crawler.utils.StringUtils;

import java.util.HashSet;
import java.util.Set;

@TaskFeature
public abstract class Task {

    public final CrawlerLogger logger = CrawlerLogger.getLogger(getClass().getSuperclass());

    private String id = StringUtils.getId();

    private String crawlerId;

    private Integer index;

    private String url;

    protected Set<String> dispatchUrl = new HashSet<>();

    public Task(String crawlerId, Integer index, String url) {
        this.crawlerId = crawlerId;
        this.index = index;
        this.url = url;
    }

    public abstract <T extends Request> T buildRequest();

    public void run() throws Exception {
        TaskFeature feature = ReflectUtils.getAnnotation(getClass(), TaskFeature.class);
        Response response = Connection.create(feature.conn(), feature.charSet()).validate(buildRequest()).accept().doConvert(feature.converter());
        if (!response.isSuccess()) {
            throw new CrawlerRuntimeException(ExceptionCode.REQUEST_FAIL);
        }
        Crawler crawler = CrawlerContext.getCrawler(crawlerId);
        if (crawler == null) {
            return;
        }
        //缓存结果
        if (feature.cache()) {
            crawler.getCache().put(id, Const.TASK_RESULT, response);
        }
    }

    public void recovery() throws Exception {

    }

    public void setDispatchUrl(Set<String> dispatchUrl) {
        this.dispatchUrl = dispatchUrl;
    }

    public Set<String> getDispatchUrl() {
        return dispatchUrl;
    }

    public String getId() {
        return id;
    }

    public String getUrl() {
        return url;
    }

    public String getCrawlerId() {
        return crawlerId;
    }

    public Integer getIndex() {
        return index;
    }

}
